﻿using FCSChart.Graphical;
using System;
using System.Collections.Generic;
using System.Windows.Media;

namespace FCSChart
{
    public static class Helper
    {
        internal static readonly Color DefaultColor = new Color() { A = 0xff, R = 0x40, G = 0x90, B = 0x00 };
        internal static readonly Brush DefaultSeriesFill = new SolidColorBrush(DefaultColor);

        static readonly Random random = new Random();
        /// <summary>
        /// 获取新的颜色
        /// </summary>
        /// <returns></returns>
        public static Color GetNewColor(byte a = 0xff)
        {
            byte r = Convert.ToByte(random.Next(255));
            byte g = Convert.ToByte(random.Next(255));
            byte b = Convert.ToByte(random.Next(255));
            return new Color() { A = a, R = r, G = g, B = b };
        }
        /// <summary>
        /// 获取新的笔刷
        /// </summary>
        /// <returns></returns>
        public static SolidColorBrush GetNewSolidColorBrush(byte a = 0xff)
        {
            return new SolidColorBrush(GetNewColor(a));
        }

        /// <summary>
        /// 获取渐变颜色
        /// </summary>
        /// <param name="i">当前梯度值</param>
        /// <param name="max">最大梯度量</param>
        /// <param name="color">基础颜色</param>
        public static Color GetGradientColor(long i, long max, Color color)
        {
            if (max <= 1) return color;
            byte tempR = Convert.ToByte(255 * i / max);
            byte tempG = color.G;
            byte tempB = color.B;
            return new Color() { A = color.A, R = tempR, G = tempG, B = tempB };
        }
        /// <summary>
        /// decimal转字符串
        /// 数字过大时用科学计数法
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ToShortString(this decimal value)
        {
            int i = 0;
            var temp = value;
            while (Math.Abs(temp / 10) >= 1)
            {
                temp /= 10;
                i++;
            }
            var tempStr = string.Concat(temp, "E+", i);
            var tempStr1 = value.ToString();
            return tempStr.Length > tempStr1.Length ? tempStr1 : tempStr;
        }

        /// <summary>
        /// 已使用的区域名称集合
        /// </summary>
        public static Dictionary<string, int> GraphicalNameIndex { get; } = new Dictionary<string, int>();
        /// <summary>
        /// 创建新门的名称
        /// </summary>
        /// <param name="graphical"></param>
        /// <returns></returns>
        internal static string CreateNewNameFaction(BaseGraphical graphical)
        {
            if (!GraphicalNameIndex.ContainsKey(graphical.ShortName)) GraphicalNameIndex[graphical.ShortName] = 1;
            var index = GraphicalNameIndex[graphical.ShortName]++;
            return string.Concat(graphical.ShortName, index);
        }

        /// <summary>
        /// 添加已存在的区域名称
        /// </summary>
        /// <param name="name"></param>
        internal static void AddExistedGraphicalName(string shortName, params string[] areaNames)
        {
            if (string.IsNullOrEmpty(shortName) || areaNames == null || areaNames.Length <= 0) return;
            foreach (var areaName in areaNames)
            {
                if (string.IsNullOrEmpty(areaName) || !areaName.StartsWith(shortName)) continue;
                var number = areaName.Substring(shortName.Length);
                if (int.TryParse(number, out int n))
                {
                    if (GraphicalNameIndex.ContainsKey(shortName) && GraphicalNameIndex[shortName] <= n) GraphicalNameIndex[shortName] = n;
                    else if (!GraphicalNameIndex.ContainsKey(shortName)) GraphicalNameIndex[shortName] = n;
                }
            }
        }

        #region 内置的轴函数算法
        public static double Log10(double value)
        {
            if (double.IsNaN(value)) return value;
            else if (double.IsPositiveInfinity(value)) return double.MaxValue;
            else if (double.IsNegativeInfinity(value)) return double.MinValue;
            else if (value >= 10) return Math.Log10(value);
            else if (value <= -10) return -Math.Log10(-value);
            else return value / 10;
        }

        public static double Pow10(double value)
        {
            if (double.IsNaN(value)) return value;
            else if (double.IsPositiveInfinity(value)) return double.MaxValue;
            else if (double.IsNegativeInfinity(value)) return double.MinValue;
            else if (value >= 1) return Math.Pow(10, value);
            else if (value <= -1) return -Math.Pow(10, -value);
            else return value * 10;
        }

        public static double LogBiExp(double value)
        {
            if (double.IsNaN(value)) return value;
            else if (double.IsPositiveInfinity(value)) return double.MaxValue;
            else if (double.IsNegativeInfinity(value)) return double.MinValue;
            else return Math.Log10(0.1 * value + Math.Sqrt(0.01 * Math.Pow(value, 2) + 1)) + 0.7;
        }

        public static double PowBiExp(double value)
        {
            if (double.IsNaN(value)) return value;
            else if (double.IsPositiveInfinity(value)) return double.MaxValue;
            else if (double.IsNegativeInfinity(value)) return double.MinValue;
            else return (Math.Pow(10, 2 * (value - 0.7)) - 1) / (Math.Pow(10, value - 0.7) * 0.2);
        }

        #endregion
    }
}
